﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Xml;
using System.Web;
using System.Text.RegularExpressions;
using System.Reflection;
using WJ.Infrastructure.Extension;


namespace WJ.Infrastructure.Util
{
    public class IOUtil
    {
        #region 获取文件扩展名
        /// <summary>
        /// 获取文件扩展名
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public static string GetExtension(string fileName)
        {
            int i = fileName.LastIndexOf(".") + 1;
            string Name = fileName.Substring(i);
            return Name;
        }
        #endregion

        #region 删除文章中使用的图片

        //返回单个路径
        public static string GetImgUrl(string HTMLStr)
        {
            string str = string.Empty;
            //string sPattern = @"^<img\s+[^>]*>";
            Regex r = new Regex(@"<img\s+[^>]*\s*src\s*=\s*([']?)(?<url>\S+)'?[^>]*>",
            RegexOptions.Compiled);
            Match m = r.Match(HTMLStr.ToLower());
            if (m.Success)
                str = m.Result("${url}");
            return str;
        }
        //返回多个路径的情况
        public static string MyGetImgUrl(string text)
        {
            string str = "";
            string pat = @"<img\s+[^>]*\s*src\s*=\s*([']?)(?<url>\S+)'?[^>]*>";

            Regex r = new Regex(pat, RegexOptions.Compiled);

            Match m = r.Match(text.ToLower());
            //int matchCount = 0;
            while (m.Success)
            {
                Group g = m.Groups[2];
                str += g;
                str += ",";
                m = m.NextMatch();
            }
            return str;
        }
       
        #endregion

        #region 读取文件（默认编码）
        /// <summary>
        /// 读取文件（默认编码）
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        public static string Read(string path)
        {
            return Read(path, Encoding.Default);
        }
        #endregion

        #region 读取文件（指定编码）
        /// <summary>
        /// 读取文件（指定编码）
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="encode">编码方式</param>
        /// <returns></returns>
        public static string Read(string path, Encoding encode)
        {
            FileStream fs = null;
            for (int i = 0; i < 5; i++)
            {
                try
                {
                    if (!path.Contains(":"))
                    {
                        path = path.GetMapPath();
                    }
                    fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                    break;
                }
                catch
                {
                    System.Threading.Thread.Sleep(50);
                }
            }
            if (fs == null) return "";
            StreamReader sr = null;
            try
            {
                sr = new StreamReader(fs, encode);
                return sr.ReadToEnd();
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                sr.Dispose();
                fs.Dispose();
            }
        }
        #endregion

        #region 返回文件行的数组
        /// <summary>
        /// 返回文件行的数组
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <returns></returns>
        public static string[] ReadLines(string path)
        {
            return ReadLines(path, Encoding.Default);
        }
        /// <summary>
        /// 返回文件行的数组
        /// </summary>
        /// <param name="path">文件路径</param>
        /// <param name="encode">编码方式</param>
        /// <returns></returns>
        public static string[] ReadLines(string path, Encoding encode)
        {
            try
            {
                return File.ReadAllLines(path.GetMapPath(), encode);
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region 向文件写入内容（默认编码）
        /// <summary>
        /// 向文件写入内容（默认编码）
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="content">内容</param>
        /// <returns></returns>
        public static bool Write(string path, string content)
        {
            return Write(path, content, Encoding.Default);
        }
        #endregion

        #region 向文件写入内容（指定编码）
        /// <summary>
        /// 向文件写入内容（指定编码）
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="content">内容</param>
        /// <param name="encode">编码</param>
        /// <returns></returns>
        public static bool Write(string path, string content, Encoding encode)
        {
            FileStream fs = null;
            for (int i = 0; i < 5; i++)
            {
                try
                {
                    fs = new FileStream(path.GetMapPath(), FileMode.OpenOrCreate, FileAccess.Write, FileShare.ReadWrite);
                    break;
                }
                catch
                {
                    System.Threading.Thread.Sleep(50);
                }
            }
            if (fs == null) return false;
            StreamWriter sw = null;
            try
            {
                sw = new StreamWriter(fs, encode);
                sw.Write(content);
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                sw.Dispose();
                fs.Dispose();
            }
        }
        #endregion

        #region 向文件追加内容（默认编码）
        /// <summary>
        /// 向文件追加内容（默认编码）
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="content">内容</param>
        /// <returns></returns>
        public static bool Append(string path, string content)
        {
            return Append(path, content, Encoding.Default);
        }
        #endregion

        #region 向文件追加内容（指定编码）
        /// <summary>
        /// 向文件追加内容（指定编码）
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="content">内容</param>
        /// <param name="encode">编码</param>
        /// <returns></returns>
        public static bool Append(string path, string content, Encoding encode)
        {
            FileStream fs = null;
            for (int i = 0; i < 5; i++)
            {
                try
                {
                    fs = new FileStream(path.GetMapPath(), FileMode.Append, FileAccess.Write, FileShare.ReadWrite);
                    break;
                }
                catch
                {
                    System.Threading.Thread.Sleep(50);
                }
            }
            if (fs == null) return false;
            StreamWriter sw = null;
            try
            {
                sw = new StreamWriter(fs, encode);
                sw.Write(content);
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                sw.Dispose();
                fs.Dispose();
            }
        }
        #endregion

        #region 删除指定文件
        /// <summary>
        /// 删除指定文件
        /// </summary>
        /// <param name="path">路径</param>
        /// <returns></returns>
        public static bool Delete(string path)
        {
            try
            {
                path = path.GetMapPath();
                if (File.Exists(path))
                {
                    File.Delete(path);
                }
                return true;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }
        #endregion

        #region 获取指定目录下所有文件
        /// <summary>
        /// 获取指定目录下所有文件
        /// </summary>
        /// <param name="dir">目录</param>
        /// <returns></returns>
        public static string[] GetFiles(string dir)
        {
            try
            {
                return Directory.GetFiles(dir.GetMapPath());
            }
            catch (DirectoryNotFoundException ex)
            {
                throw ex;
            }
        }
        #endregion

        #region 获取目录中所有文件路径
        /// <summary>
        /// 获取目录中所有文件路径
        /// </summary>
        /// <param name="dir">目录</param>
        /// <param name="patt">匹配正则(如：*.(txt|log))</param>
        /// <returns></returns>
        public static List<string> GetFiles(string dir, string patt)
        {
            string pattern = "(?i)^" + patt.Replace(".", @"\.") + "$";

            Regex reg = new Regex(pattern);

            List<string> list = new List<string>();

            try
            {
                string[] files = Directory.GetFiles(dir.GetMapPath());

                foreach (string file in files)
                {
                    if (reg.IsMatch(file))
                        list.Add(file);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            return list;
        }
        #endregion

        #region 根据文件路径，或文件夹路径，创建文件夹
        /// <summary>
        /// 根据文件路径，或文件夹路径，创建文件夹
        /// </summary>
        /// <param name="dir"></param>
        public static void IfNotExistsCreateDir(string dir)
        {
            //dir = dir.GetMapPath();
            if (dir.Contains("."))
            {
                dir = dir.Substring(0, dir.LastIndexOf("\\"));
            }
            if (!Directory.Exists(dir))
            {
                Directory.CreateDirectory(dir);
            }
        }
        #endregion

        #region 返回所给文件路径的字节数组
        /// <summary>
        /// getBinaryFile：返回所给文件路径的字节数组。
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        public static byte[] getBinaryFile(string filename)
        {
            filename = filename.GetMapPath();
            if (File.Exists(filename))
            {
                try
                {
                    ///打开现有文件以进行读取。
                    using (FileStream s = File.OpenRead(filename))
                    {
                        return ConvertStreamToByteBuffer(s);
                    }
                   
                }
                catch
                {
                    return new byte[0];
                }
            }
            else
            {
                return new byte[0];
            }
        }
        #endregion

        #region ConvertStreamToByteBuffer：把给定的文件流转换为二进制字节数组
        /// <summary>
        /// ConvertStreamToByteBuffer：把给定的文件流转换为二进制字节数组。
        /// </summary>
        /// <param name="theStream"></param>
        /// <returns></returns>
        public static byte[] ConvertStreamToByteBuffer(System.IO.Stream theStream)
        {
            int b1;
            using (System.IO.MemoryStream tempStream = new System.IO.MemoryStream())
            {
                while ((b1 = theStream.ReadByte()) != -1)
                {
                    tempStream.WriteByte(((byte)b1));
                }
                return tempStream.ToArray();
            }

        }
        #endregion

        #region 保存文件
        /// <summary>
        /// 保存文件
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="fileName"></param>
        public static void StreamToFile(Stream stream, string fileName)
        {
            using (stream)
            {
                // 把 Stream 转换成 byte[] 
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);

                IfNotExistsCreateDir(fileName);

                File.WriteAllBytes(fileName, bytes);
            }

            // 设置当前流的位置为流的开始 
            //stream.Seek(0, SeekOrigin.Begin);
            //// 把 byte[] 写入文件 
            //FileStream fs = new FileStream(fileName.GetMapPath(), FileMode.OpenOrCreate);
            //BinaryWriter bw = new BinaryWriter(fs);
            //try
            //{
            //    bw.Write(bytes);
            //}
            //finally
            //{
            //    bw.Close();
            //    fs.Close();
            //}
        }
        #endregion

        #region 读取文件
        /// <summary>
        /// 读取文件
        /// </summary>
        /// <param name="fileName"></param>
        /// <returns></returns>
        public Stream FileToStream(string fileName)
        {
            // 打开文件 
            FileStream fileStream = new FileStream(fileName.GetMapPath(), FileMode.Open, FileAccess.Read, FileShare.Read);
            // 读取文件的 byte[] 
            byte[] bytes = new byte[fileStream.Length];
            try
            {
                fileStream.Read(bytes, 0, bytes.Length);
            }
            finally
            {
                fileStream.Close();
                fileStream.Dispose();
            }
            // 把 byte[] 转换成 Stream 
            Stream stream = new MemoryStream(bytes);
            return stream;
        }
        #endregion

        #region 加载实现某接口的dll

        /// <summary>
        /// 加载实现某接口的类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <returns></returns>
        public static List<Type> LoadType<T>(string path) where T : class
        {
            List<Type> list = new List<Type>();

            var files = IOUtil.GetFiles(path);

            foreach (var file in files)
            {
                if (!file.EndsWith("dll"))
                {
                    continue;
                }
                try
                {
                    //var ass = Assembly.LoadFrom(file);

                    byte[] assemblyBuf = File.ReadAllBytes(file);
                    Assembly ass = Assembly.Load(assemblyBuf);

                    foreach (var t in ass.GetExportedTypes())
                    {

                        if (t.IsClass && typeof(T).IsAssignableFrom(t))
                        {
                            list.Add(t);
                        }
                    }
                }
                catch
                {
                    continue;
                }
            }

            return list;
        }
        /// <summary>
        /// 加载实现某接口的dll
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="path"></param>
        /// <returns></returns>
        public static List<T> LoadDll<T>(string path, params object[] param) where T : class
        {

            List<T> dllList = new List<T>();

            var typeList = LoadType<T>(path);

            foreach (var t in typeList)
            {
                T obj = null;
                if (param != null)
                {
                    obj = Activator.CreateInstance(t, param) as T;
                }
                else
                {
                    obj = Activator.CreateInstance(t) as T;
                }
                dllList.Add(obj);
            }

            return dllList;

        }

        private static string m_AssemblyDirectory = null;
        /// <summary>
        /// 获得运行exe或dll的目录
        /// </summary>
        /// <returns>返回目录字符串</returns>
        public static string AssemblyDirectory
        {
            get
            {
                if (string.IsNullOrEmpty(m_AssemblyDirectory))
                {
                    string binPath = "";
                    HttpContext context = HttpContext.Current;
                    if (context != null)
                    {
                        binPath = context.Server.MapPath("/bin/");
                    }
                    if (string.IsNullOrEmpty(binPath))
                    {
                        Assembly assembly = Assembly.GetCallingAssembly();
                        FileInfo AssemblyFileInfo = new FileInfo(assembly.Location);
                        binPath = AssemblyFileInfo.DirectoryName;
                    }
                    m_AssemblyDirectory = binPath;
                }
                return m_AssemblyDirectory;
            }
        }

        /// <summary>
        /// 加载<see cref="path"/>目录下的应用程序集
        /// </summary>
        /// <param name="load">加载动作</param>
        /// <param name="pattern">扩展名</param>
        /// <param name="path">指定加载的目录，默认是运行目录</param>
        /// <param name="except">排除一些程序集的方法</param>      
        /// <param name="shadow">加载影子dll</param>
        public static void LoadAssembly(
            Action<Assembly> load,
            string pattern = "*.*",
            string path = "",
            Func<string, bool> except = null,
            bool shadow = false)
        {

            string adjustPath = path;

            if (string.IsNullOrWhiteSpace(adjustPath))
            {
                adjustPath = AssemblyDirectory;
            }

            DirectoryInfo dirInfo = new DirectoryInfo(adjustPath);
            foreach (FileInfo file in dirInfo.GetFiles(pattern))
            {
                bool isFilePass = true;
                if (except != null)
                {
                    isFilePass = !except(file.FullName);

                }

                if (isFilePass)
                {
                    Assembly assembly;
                    if (!shadow)
                    {
                        assembly = Assembly.LoadFile(file.FullName);
                    }
                    else
                    {
                        string dllName = file.Name.Remove(file.Name.LastIndexOf("."));
                        assembly = Assembly.Load(dllName);
                    }
                    load(assembly);
                }
            }
        }
        #endregion

    }
}
